import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:ball_lion/entity/ai/chart_line_entity.dart';
import 'package:ball_lion/entity/ai/chart_match_entity.dart';
import 'package:ball_lion/resources/colours.dart';
import 'package:ball_lion/resources/styles.dart';
import 'package:ball_lion/utils/utils.dart';
import 'package:ball_lion/utils/widget_utils.dart';
import 'package:ball_lion/module/pick/ai/ai_type.dart';
import 'package:ball_lion/module/pick/items/chart_info_row.dart';
import 'package:ball_lion/module/pick/items/chart_match_info.dart';
import 'package:ball_lion/widgets/circular.dart';
import 'package:ball_lion/widgets/loading/loading_widget.dart';
import 'package:ball_lion/server/api/ai_api.dart';
import 'package:ball_lion/widgets/card.dart';
import 'package:ball_lion/widgets/base/wqs_text.dart';
import 'chart_notice.dart';

class ChartLinePage extends StatefulWidget {
  const ChartLinePage({super.key, required this.type, required this.matchId});

  final AiType type;
  final int matchId;

  @override
  State<ChartLinePage> createState() => _ChartLinePageState();
}

class _ChartLinePageState extends State<ChartLinePage> {
  ChartLineEntity? entity;
  List<Color> color = [
    Colours.main,
    const Color(0xFF165DFF),
    const Color(0xFF17C4C4)
  ];
  List<String> type = ["胜", "平", "负"];
  List<String> text = [];
  List<bool> show = List.generate(3, (index) => true);
  Map<int, List<double>> lineData = {0: [], 1: [], 2: []};
  int distance = 4;

  @override
  void initState() {
    getData();
    super.initState();
  }

  Future getData() async {
    ChartLineEntity? data =
        await AiApi.getLine(widget.matchId, widget.type.tag);
    setState(() {
      entity = data;
      entity?.list?.forEach((element) {
        lineData[0]?.add(element.s ?? 0);
        if (widget.type == AiType.pre) {
          lineData[1]?.add(element.line ?? 0);
        } else {
          lineData[1]?.add(element.p ?? 0);
        }
        lineData[2]?.add(element.f ?? 0);
      });
      text = [entity?.s ?? "", entity?.p ?? "", entity?.f ?? ""];
      var index46 = entity?.list?.indexWhere((element) => element.i == 46);
      var index50 = entity?.list?.indexWhere((element) => element.i == 50);
      if (index50 != null && index46 != null) distance = index50 - index46;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: Styles.appBar(
          titleSpacing: 0,
          titleTextStyle: const TextStyle(fontSize: 14, color: Colours.text),
          title: QsText(widget.type.name,
              fontWeight: FontWeight.w500, fontSize: 18)),
      backgroundColor: Colours.greyF2F3F7,
      body: LoadingWidget<bool>(
        isLoading: entity == null,
        data: entity?.matchId == null,
        child: () => SingleChildScrollView(
          child: Column(
            children: [
              Block(
                  cardStyle: const CardStyle(
                      margin: EdgeInsets.fromLTRB(12, 12, 12, 0)),
                  child: Column(
                    children: [
                      Container(height: 12),
                      ChartMatchInfo(
                          info: ChartMatchEntity.fromJson(entity!.toJson())),
                      Container(height: 20),
                      ChartInfoRow(advice: entity?.option?.join("、") ?? "")
                    ],
                  )),
              Circular(
                margin: const EdgeInsets.fromLTRB(12, 12, 12, 0),
                padding: const EdgeInsets.all(16),
                radius: 8,
                color: Colours.white,
                child: Column(
                  children: [
                    Row(
                      children: [
                        QsText(
                            "${widget.type == AiType.trend ? "胜平负" : "让球"}走势",
                            fontSize: 16,
                            fontWeight: FontWeight.w500),
                        const Spacer(),
                        Row(
                            children: List.generate(
                                    type.length, (index) => showItem(index))
                                .insertEvery(Container(width: 16))),
                      ],
                    ),
                    Container(height: 30),
                    if (widget.type == AiType.trend && entity != null)
                      trendChart(),
                    if (widget.type == AiType.pre && entity != null)
                      ...List.generate(3, (index) => preChart(index)),
                    ChartNotice(
                        tips: entity?.tips ?? [],
                        margin: const EdgeInsets.only(top: 24)),
                    if (widget.type == AiType.trend)
                      Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          const QsText("近期战绩",
                              fontSize: 16, fontWeight: FontWeight.w500),
                          Container(height: 12),
                          Block(
                              cardStyle: const CardStyle(
                                  color: Color(0xFFF7FAFF),
                                  padding: EdgeInsets.fromLTRB(12, 8, 12, 8)),
                              child: Column(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: List.generate(text.length,
                                        (index) => item(text[index], index))
                                    .insertEvery(Container(height: 9)),
                              )),
                        ],
                      ).paddingOnly(top: 24)
                  ],
                ),
              ),
              Container(height: 50)
            ],
          ),
        ),
      ),
    );
  }

  Widget trendChart() {
    return SizedBox(
      height: 220,
      child: LineChart(LineChartData(
          minY: entity?.min,
          baselineY: (entity?.min ?? 0) - 0.001,
          lineBarsData: [
            if (show[0]) line(0),
            if (show[1]) line(1),
            if (show[2]) line(2)
          ],
          titlesData: FlTitlesData(
              topTitles:
                  const AxisTitles(axisNameSize: 0, axisNameWidget: QsText("")),
              rightTitles:
                  const AxisTitles(axisNameWidget: QsText(""), axisNameSize: 0),
              leftTitles: AxisTitles(
                  sideTitles: SideTitles(
                reservedSize: 40,
                showTitles: true,
                interval: ((entity?.max ?? 10) - (entity?.min ?? 0)) / 5,
                getTitlesWidget: (value, meta) {
                  return SideTitleWidget(
                    axisSide: meta.axisSide,
                    child: QsText(value.toStringAsFixed(2),
                        fontSize: 12, color: Colours.grey99),
                  );
                },
              )),
              bottomTitles: AxisTitles(
                  sideTitles: SideTitles(
                      showTitles: true,
                      interval: 1,
                      reservedSize: distance <= 4 ? 34 : 22,
                      getTitlesWidget: (value, meta) {
                        TextStyle style = const TextStyle(
                            fontSize: 12,
                            color: Colours.grey99,
                            overflow: TextOverflow.ellipsis);
                        switch (entity?.list?[value.toInt()].i) {
                          case 1:
                            return SideTitleWidget(
                              space: 6,
                              axisSide: meta.axisSide,
                              child: QsText.style("初", style: style),
                            );
                          case 46:
                            return SideTitleWidget(
                              space: 6,
                              axisSide: meta.axisSide,
                              fitInside:
                                  SideTitleFitInsideData.fromTitleMeta(meta),
                              child: QsText.style("赛前5小时",
                                  textAlign: TextAlign.center, style: style),
                            );
                          case 50:
                            return SideTitleWidget(
                              space: distance <= 4 ? 18 : 6,
                              axisSide: meta.axisSide,
                              fitInside:
                                  SideTitleFitInsideData.fromTitleMeta(meta),
                              child: QsText.style("开赛", style: style),
                            );
                          default:
                            return const QsText("");
                        }
                      }))),
          gridData: FlGridData(
              horizontalInterval:
                  ((entity?.max ?? 10) - (entity?.min ?? 0)) / 5,
              verticalInterval: 1,
              checkToShowVerticalLine: (value) =>
                  entity?.list?[value.toInt()].i == 46,
              getDrawingVerticalLine: (value) =>
                  const FlLine(color: Colours.greyD7, strokeWidth: 1),
              getDrawingHorizontalLine: (value) => const FlLine(
                  color: Colours.greyD7, dashArray: [3, 3], strokeWidth: 1)),
          borderData: FlBorderData(
              border: const Border(
                  bottom: BorderSide(color: Colours.greyD7, width: 1))),
          lineTouchData: LineTouchData(
              touchCallback:
                  (FlTouchEvent event, LineTouchResponse? response) {},
              touchTooltipData: LineTouchTooltipData(
                  getTooltipColor: (LineBarSpot touchedSpot) {
                    return Colors.white;
                  },
                  fitInsideVertically: true,
                  fitInsideHorizontally: true,
                  tooltipHorizontalOffset: 10,
                  tooltipBorder:
                      const BorderSide(color: Colours.greyD7, width: 0.5),
                  tooltipHorizontalAlignment: FLHorizontalAlignment.right,
                  getTooltipItems: (touchedSpots) => touchedSpots
                      .map((e) => LineTooltipItem(e.y.toStringAsFixed(2),
                          TextStyle(color: e.bar.color, fontSize: 12)))
                      .toList()),
              getTouchedSpotIndicator: (barData, indicators) => indicators
                  .map((e) => TouchedSpotIndicatorData(
                      const FlLine(color: Colours.greyD7, strokeWidth: 1),
                      FlDotData(
                          getDotPainter: (spot, xPercentage, bar, index) =>
                              FlDotCirclePainter(
                                  radius: 3,
                                  strokeColor:
                                      barData.color?.withOpacity(0.5) ??
                                          Colours.transparent,
                                  color: barData.color ?? Colours.transparent,
                                  strokeWidth: 2))))
                  .toList()))),
    );
  }

  Widget preChart(int index) {
    var max = (lineData[index]?.max() ?? 0.1).abs();
    var min = (lineData[index]?.min() ?? 0).abs();
    double middleInterval = (min > max ? min - max : max - min) / 2;
    double middleValue = middleInterval + (lineData[index]?.min() ?? 0);
    return SizedBox(
      height: index == 2 ? (220 / 3) + 22 : 220 / 3,
      child: LineChart(
          curve: Curves.easeInToLinear,
          LineChartData(
              baselineY: lineData[index]?.min()?.toDouble(),
              minY: lineData[index]?.min()?.toDouble(),
              lineBarsData: [line(index)],
              titlesData: FlTitlesData(
                  topTitles: const AxisTitles(axisNameWidget: QsText("")),
                  rightTitles: const AxisTitles(axisNameSize: 0),
                  leftTitles: AxisTitles(
                      sideTitles: SideTitles(
                          reservedSize: 34,
                          showTitles: true,
                          interval: middleInterval,
                          getTitlesWidget: (value, meta) {
                            if (meta.formattedValue ==
                                middleValue.toStringAsFixed(2)) {
                              String text = "";
                              switch (index) {
                                case 0:
                                  text = "主水";
                                  break;
                                case 1:
                                  text = "让";
                                  break;
                                case 2:
                                  text = "客水";
                                  break;
                              }
                              return SideTitleWidget(
                                axisSide: meta.axisSide,
                                child: QsText(
                                    "$text\n${lineData[index]?[0].toStringAsFixed(1)}",
                                    textAlign: TextAlign.center,
                                    color: Colours.grey99,
                                    fontSize: 12),
                              );
                            } else {
                              return const QsText("");
                            }
                          })),
                  bottomTitles: AxisTitles(
                      sideTitles: SideTitles(
                          showTitles: index == 2 ? true : false,
                          interval: 1,
                          reservedSize: distance <= 4 ? 34 : 22,
                          getTitlesWidget: (value, meta) {
                            TextStyle style = const TextStyle(
                                fontSize: 12,
                                color: Colours.grey99,
                                overflow: TextOverflow.ellipsis);
                            switch (entity?.list?[value.toInt()].i) {
                              case 1:
                                return SideTitleWidget(
                                  space: 6,
                                  axisSide: meta.axisSide,
                                  child: QsText.style("初", style: style),
                                );
                              case 46:
                                return SideTitleWidget(
                                  space: 6,
                                  axisSide: meta.axisSide,
                                  fitInside:
                                      SideTitleFitInsideData.fromTitleMeta(meta,
                                          distanceFromEdge:
                                              (entity?.list?.length ?? 0) > 36
                                                  ? 22
                                                  : 6),
                                  child: QsText.style("赛前5小时",
                                      textAlign: TextAlign.center,
                                      style: style),
                                );
                              case 50:
                                return SideTitleWidget(
                                    space: distance <= 4 ? 18 : 6,
                                    axisSide: meta.axisSide,
                                    fitInside:
                                        SideTitleFitInsideData.fromTitleMeta(
                                            meta,
                                            distanceFromEdge: 0),
                                    child: QsText.style("开赛", style: style));
                              default:
                                return const QsText("");
                            }
                          }))),
              gridData: FlGridData(
                  drawHorizontalLine: true,
                  horizontalInterval: middleInterval,
                  verticalInterval: 1,
                  checkToShowVerticalLine: (value) =>
                      entity?.list?[value.toInt()].i == 46,
                  getDrawingVerticalLine: (value) =>
                      const FlLine(color: Colours.greyD7, strokeWidth: 1),
                  getDrawingHorizontalLine: (value) => const FlLine(
                      color: Colours.greyD7,
                      dashArray: [3, 3],
                      strokeWidth: 1)),
              borderData: FlBorderData(
                  show: index == 2 ? true : false,
                  border: const Border(
                      bottom: BorderSide(color: Colours.greyD7, width: 1))),
              lineTouchData: LineTouchData(
                  touchCallback:
                      (FlTouchEvent event, LineTouchResponse? response) {},
                  touchTooltipData: LineTouchTooltipData(
                      getTooltipColor: (LineBarSpot touchedSpot) {
                        return Colors.white;
                      },
                      fitInsideVertically: true,
                      fitInsideHorizontally: true,
                      tooltipHorizontalOffset: 10,
                      tooltipBorder:
                          const BorderSide(color: Colours.greyD7, width: 0.5),
                      tooltipHorizontalAlignment: FLHorizontalAlignment.right,
                      getTooltipItems: (touchedSpots) => touchedSpots
                          .map((e) => LineTooltipItem(e.y.toStringAsFixed(2),
                              TextStyle(color: e.bar.color, fontSize: 12)))
                          .toList()),
                  getTouchedSpotIndicator: (barData, indicators) => indicators
                      .map((e) => TouchedSpotIndicatorData(
                          const FlLine(
                              color: Colours.transparent, strokeWidth: 1),
                          FlDotData(
                              getDotPainter: (spot, xPercentage, bar, i) =>
                                  FlDotCirclePainter(
                                      radius: 2,
                                      strokeColor:
                                          barData.color?.withOpacity(0.5) ??
                                              Colours.transparent,
                                      color:
                                          barData.color ?? Colours.transparent,
                                      strokeWidth: 2))))
                      .toList()))),
    );
  }

  Widget item(String text, int index) {
    return Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
      Container(
          width: 4,
          height: 4,
          margin: const EdgeInsets.only(top: 6),
          alignment: Alignment.center,
          decoration:
              BoxDecoration(shape: BoxShape.circle, color: color[index])),
      Container(width: 8),
      Flexible(
          child: QsText(
        text.split("").join('\u200A'),
        color: Colours.grey66,
        maxLines: 2,
        letterSpacing: -0.8,
        needCenter: true,
      ))
    ]);
  }

  Widget showItem(int index) {
    return Row(
      children: [
        SizedBox(
          width: 16,
          height: 16,
          child: Stack(
            children: [
              Container(
                width: 16,
                height: 16,
                decoration: BoxDecoration(
                    shape: BoxShape.circle,
                    color: Colours.white,
                    border: Border.all(color: color[index], width: 1)),
              ),
              Align(
                  alignment: Alignment.center,
                  child: Container(
                    width: 12,
                    height: 12,
                    decoration: BoxDecoration(
                        color: show[index] ? color[index] : Colours.white,
                        shape: BoxShape.circle),
                  ))
            ],
          ),
        ).tap(() => setState(() => show[index] = !show[index])),
        Container(width: 4),
        QsText(type[index], color: color[index], fontSize: 12, needCenter: true)
      ],
    );
  }

  LineChartBarData line(int index) {
    return LineChartBarData(
        show: show[index],
        barWidth: 1.5,
        isCurved: true,
        spots: List.generate(entity?.list?.length ?? 0,
            (i) => FlSpot(i.toDouble(), lineData[index]?[i] ?? 0)),
        color: color[index],
        belowBarData: BarAreaData(
          show: true,
          gradient: LinearGradient(
              colors: [color[index].withOpacity(0.2), Colours.transparent],
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              stops: const [0, 0.4]),
        ),
        dotData: FlDotData(
            show: false,
            getDotPainter: (spot, xPercentage, bar, potIndex) =>
                FlDotCirclePainter(
                    radius: 3,
                    color: color[index],
                    strokeWidth: 2,
                    strokeColor: color[index].withOpacity(0.5))));
  }
}
